;	This code is tested;
;	the interface for its usage could use some improvement
;	and apparently loading save data while online causes
;	desynchronization

;	Co-Op Save Hack
.long				0xC0DE0000
.long				0x00000000

;-------------------------------;
;	Co-Op Save Hack		;
;-------------------------------;
;	The first part of this code backs up 1 player data when L is held in single player mode
;	It recovers the back up after multiplayer mode has been entered

;Copy to/from specified backup save RAM
LUI	S1,	0x800A		;
LB	S2,	0x5060	(S1)	;Check mode

BNEZ	S2,			From
;-------------------------------;

;-------------------------------;
;	Single player mode	;
;-------------------------------;

LUI	S1,	0x8010		;
LH	S2,	0x5304	(S1)	;
XORI	S2,	S2,	0x0020	;Check L button; CopyTo if only L pressed

BNEZ	S2,			NoCopy

;-------------------------------;
;	>	L pressed	;
;-------------------------------;

				CopyTo:
LUI	S1,	0x801E		;
ORI	S1,	S1,	0x6010	;S1 = Save data ptr
LUI	S2,	0x800B		;S2 = Custom save data ptr
ORI	S2,	S2,	0x6800	;
LUI	S3,		0x801E	;
ORI	S3,	S3,	0x6580	;S3 = Termination ptr
SW	R0,	-0x000C	(S2)	;Set "have warped" boolean to "false"
SW	R0,	-0x0008	(S2)	;Set 1st test ptr to null
SW	R0,	-0x0004	(S2)	;Set 2nd test ptr to null

;-------------------------------;
;	4 byte memcpy code	;
;-------------------------------;
;S1 = src
;S2 = dest
;S3 = should point to after end of src data

				ToLoop:
LW	S0,	0x0000	(S1)	;
SW	S0,	0x0000	(S2)	;
ADDIU	S1,	S1,	0x0004	;
ADDIU	S2,	S2,	0x0004	;

BEQ	S1,	S3,		NoCopy
NOP

BEQZ	R0,			ToLoop
NOP

;-------------------------------;
;	Multiplayer mode	;
;-------------------------------;

				From:
LUI	S1,		0x800B	;
LW	S2,	0x67FC	(S1)	;Check 2nd test ptr

BNEZ	S2,			NoCopy

;-------------------------------;
;	>	2nd test ptr not set
;-------------------------------;
;	Sets 2nd test ptr
;	Used to keep this block from being unecessarily repeated

ORI	S1,	S1,	0x6800	;S1 = Custom save data ptr
LUI	S2,		0x801E	;
ORI	S2,	S2,	0x6010	;S2 = Save data ptr
LUI	S3,		0x800B	;
ORI	S3,	S3,	0x6D70	;S3 = Termination ptr
SW	S2,	-0x0004	(S1)	;Write 2nd test ptr

BEQZ	R0,			ToLoop
NOP

;-------------------------------;
;	Copying done		;
;-------------------------------;
;	This part of the code helps with loading 1 player mode data in multi
;	It also ensures multiplayer data will be copied to the RAM that is saved during saving

				NoCopy:
;Co-Op save RAM fix if in multi mode
LUI	S1,		0x800A	;
LB	S2,	0x5060	(S1)	;Get mode byte

BEQZ	S2,			Co_Op_Save_Hack_End

;-------------------------------;
;	Multiplayer mode with copying done
;-------------------------------;

;Copy to multi or from multi
LUI	S1,		0x800B	;
LW	S2,	0x67F8	(S1)	;Load 1st test ptr

BNEZ	S2,			Saverize

;-------------------------------;
;	>	1st test ptr not set
;-------------------------------;

LUI	S1,		0x8010	;
LH	S2,	0x5304	(S1)	;
XORI	S2,	S2,	0x0020	;Check L button; Uberize if only L is pressed

BNEZ	S2,			Co_Op_Save_Hack_End

;-------------------------------;
;	>>	L was pressed	;
;-------------------------------;
;	Sets 1st test ptr
;	Used to know whether to poll for the L button
;	Sets global to "L pressed"

				Uberize:
;-------------------------------;Copy to multi
LUI	S2,		0x800B	;
SW	S2,	0x67F8	(S2)	;Write 1st test ptr
ORI	S3,	R0,	0x0020	;"L pressed"
SH	S3,	0x67F0	(S2)	;Written to last_keys global

LUI	S3,		0x800B	;
ORI	S3,	S3,	0x695C	;S3 = Termination ptr
LUI	S2,		0x800F	;
ORI	S2,	S2,	0xED66	;Multiplayer data ptr
LUI	S1,		0x800B	;
ORI	S1,	S1,	0x695C	;Section 1

				CopyToLoop:
LH	S0,	0x0000	(S1)	;
SH	S0,	0x0000	(S2)	;
ADDIU	S1,	S1,	0x0002	;
ADDIU	S2,	S2,	0x0002	;

LUI	S0,		0x800B	;
ORI	S0,	S0,	0x69D2	;Section 1 termination ptr
BEQL	S1,	S0,		CopyToLoop
ADDIU	S2,	S2,	0x002A	;

LUI	S0,		0x800B	;
ORI	S0,	S0,	0x6A48	;Section 2 termination ptr
BEQL	S1,	S0,		CopyToLoop
ADDIU	S2,	S2,	0x002A	;

LUI	S0,		0x800B	;
ORI	S0,	S0,	0x6ABE	;Section 3 termination ptr
BNE	S1,	S0,		AdvanceCopyToLoop
NOP

ADDIU	S2,	S2,	0x002A	;
ADDIU	S1,	S1,	-0x01D8	;Allocate player 4's data prior to player 1's

BEQZ	R0,			CopyToLoop
NOP

				AdvanceCopyToLoop:
BNE	S1,	S3,		CopyToLoop
NOP

BEQZ	R0,			Co_Op_Save_Hack_End
;	NOP unnecessary

				Saverize:
;-------------------------------;Copy from multi
LUI	S3,		0x801E	;
ORI	S3,	S3,	0x616C	;S3 = Termination ptr
LUI	S2,		0x800F	;
ORI	S2,	S2,	0xED66	;
LUI	S1,		0x801E	;
ORI	S1,	S1,	0x616C	;

				CopyFromLoop:
LH	S0,	0x0000	(S2)	;
SH	S0,	0x0000	(S1)	;
ADDIU	S1,	S1,	0x0002	;
ADDIU	S2,	S2,	0x0002	;

LUI	S0,		0x801E	;
ORI	S0,	S0,	0x61E2	;Section 1 termination ptr
BEQL	S1,	S0,		CopyFromLoop
ADDIU	S2,	S2,	0x002A	;

LUI	S0,		0x801E	;
ORI	S0,	S0,	0x6258	;Section 2 termination ptr
BEQL	S1,	S0,		CopyFromLoop
ADDIU	S2,	S2,	0x002A	;

LUI	S0,		0x801E	;
ORI	S0,	S0,	0x62CE	;Section 3 termination ptr
BNE	S1,	S0,		AdvanceCopyFromLoop
NOP

ADDIU	S2,	S2,	0x002A	;
ADDIU	S1,	S1,	-0x01D8	;Allocate player 4's data prior to player 1's
BEQZ	R0,			CopyFromLoop
NOP

				AdvanceCopyFromLoop:
BNE	S1,	S3,		CopyFromLoop
NOP
				Co_Op_Save_Hack_End:
JR	RA
NOP

.align				3
.long				0xE0000000
.long				0x00000000
;	End of Co-Op Save Hack
